const db = wx.cloud.database();
const cred = require('./credentials');
const datetime = require('./datetime');

const articles = () => {
  return db.collection('articles');  
};

const cards = () => {
  return db.collection('cards');
};

const books = () => {
  return db.collection('books');
};

const records = () => {
  return db.collection('records');
};

const _ = db.command;

const MONTH_OFFSET = 30 * 24 * 60 * 60 * 1000;
const WEEK_OFFSET = 7 * 24 * 60 * 60 * 1000;

const getCardsSince = (timestamp = Date.now() - MONTH_OFFSET) => {
  return articles().where({
    publishTime: _.gt(timestamp)
  }).get();
};

const getRecords = (limit = 20, skip = Date.now(), duration = Date.now()) => {
  return wx.cloud.callFunction({
    name: 'listRecords',
    data: {
      listOnlyOpen: false,
      dateSkip: skip,
      duration: duration,
      limit: limit
    }
  }).then(out => out.result.result.list);
};

const getActiveRecords = (limit = 20, skip = Date.now(), duration = Date.now()) => {
  return wx.cloud.callFunction({
    name: 'listRecords',
    data: {
      listOnlyOpen: true,
      dateSkip: skip,
      duration: duration,
      limit: limit
    }
  }).then(out => out.result.result.list);
};

const getRecord = (recordId) => {
  return wx.cloud.callFunction({
    name: 'getRecord',
    data: {
      id: recordId
    }
  }).then(out => out.result.result.list[0]);
};

const queryBooks = (name) => {
  return wx.cloud.callFunction({
    name: 'findBooksByName',
    data: {
      name: name
    }
  }).then(out => {
    console.log(out);
    return out.result
  });
};

const getBook = (bookId) => {
  return db.collection('books').where({
    _id: _.eq(bookId)
  }).limit(1).get();
};

const getBookByIsbn = (isbn) => {
  return db.collection('books').where({
    isbn: _.eq(isbn)
  }).limit(1).get();
};

const addHistory = async (bookId) => {
  const id = await cred.getOpenId();
  const ts = datetime.getTimestampOfToday();
  const q = await db.collection('histories').where({
    time: _.gt(ts)
  }).get();

  if (q.data.length > 0) {
    await db.collection('histories').doc(q.data[0]._id).update({
      data: {
        time: Date.now()
      }
    });
  } else {
    await db.collection('histories').add({
      data: {
        openid: id,
        book: bookId,
        time: Date.now()
      }
    });
  }
};

const listHistories = (limit = 20, dateSkip = Date.now(), duration = WEEK_OFFSET) => {
  return wx.cloud.callFunction({
    name: 'listHistories',
    data: {
      dateSkip: dateSkip,
      duration: duration,
      limit: limit
    }
  }).then(out => out.result.result.list);
};

const addFavorite = async (bookId) => {
  const id = await cred.getOpenId();
  await db.collection('favorites').add({
    data: {
      openid: id,
      book: bookId,
      time: Date.now()
    }
  });
};

const listFavorites = (limit = 20, skip = 0) => {
  return wx.cloud.callFunction({
    name: 'listFavorites',
    data: {
      skip: skip,
      limit: limit
    }
  }).then(out => out.result.result.list);
};

const removeFavorite = (bookId) => {
  return db.collection('favorites').where({
    book: bookId
  }).remove();
};

const isFavorite = async (bookId) => {
  const count = await db.collection('favorites').where({
    book: _.eq(bookId)
  }).count();
  return count.total > 0;
};

const listDeliveries = (limit = 20, dateSkip = Date.now(), duration = WEEK_OFFSET) => {
  return wx.cloud.callFunction({
    name: 'listDeliveries',
    data: {
      skip: dateSkip,
      duration: duration,
      limit: limit
    }
  }).then(out => out.result.result.data);
};

const makeBorrowDelivery = async (bookId) => {
  const res = await getBook(bookId);
  const book = res.data[0];

  if (book == null) {
    return -1;
  }

  const locations = book.location.filter(it => it.present);
  
  if (locations.length < 1) {
    return -1;
  }

  const targetLocation = locations[Math.floor(Math.random() * locations.length)];

  const deshelfResult = await wx.cloud.callFunction({
    name: 'deshelf',
    data: {
      id: bookId,
      location: targetLocation.location
    }
  });

  console.log('deshelf', deshelfResult);

  if (deshelfResult.result.code != 0) {
    return deshelfResult.code;
  }

  const poolId = deshelfResult.result.result;

  const result = await wx.cloud.callFunction({
    name: 'newDelivery',
    data: {
      id: poolId,
      direction: 'borrow'
    }
  });

  console.log('delivery', result);

  return result.result.code;
};

const makeReturnDelivery = (recordId) => {
  return wx.cloud.callFunction({
    name: 'newDelivery',
    data: {
      id: recordId,
      direction: 'return'
    }
  }).then(out => out.code);
};

const cancelDelivery = (deliveryId) => {
  return wx.cloud.callFunction({
    name: 'finishDelivery',
    data: {
      id: deliveryId
    }
  }).then(out => out.code);
};

const getDelivery = (deliveryId) => {
  return wx.cloud.callFunction({
    name: 'getDelivery',
    data: {
      id: deliveryId
    }
  }).then(out => out.result);
};

module.exports = {
  articles: articles,
  cards: cards,
  books: books,
  records: records,
  _: _,
  getCards: getCardsSince,
  getRecords: getRecords,
  getActiveRecords: getActiveRecords,
  getRecord: getRecord,
  addHistory: addHistory,
  listHistories: listHistories,
  addFavorite: addFavorite,
  removeFavorite: removeFavorite,
  isFavorite: isFavorite,
  listFavorites: listFavorites,
  getBook: getBook,
  getBookByIsbn: getBookByIsbn,
  listDeliveries: listDeliveries,
  makeBorrowDelivery: makeBorrowDelivery,
  makeReturnDelivery: makeReturnDelivery,
  cancelDelivery: cancelDelivery,
  getDelivery: getDelivery,
  queryBooks: queryBooks,
};
